package com.sharp.join.tk.mybatis.framework.join;

import com.sharp.join.tk.mybatis.framework.join.entity.DbField;
import com.sharp.join.tk.mybatis.framework.join.entity.JoinRelationship;
import com.sharp.join.tk.mybatis.utils.ReflectionUtil;
import lombok.extern.slf4j.Slf4j;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;

import java.util.*;

/**
 * Title: JoinSqlHelper
 * Description: Copyright: Copyright (c) 2019 Company: BHFAE
 *
 * @author Sharp
 * @date 2022/7/1 15:58
 */
@Slf4j
public class JoinSqlHelper {
    @SuppressWarnings("unchecked")
    public static String fromJoinTable(Class<?> entityClass, String defaultTableName) {
        Set<String> alreadyJoinTable = new HashSet<>();
        Object entity = ReflectionUtil.newInstance(entityClass);
        List<JoinRelationship> joinRelationshipList = (List<JoinRelationship>) ReflectionUtil.invoke(entity, "joinRelationship");
        StringBuilder sql = new StringBuilder();
        sql.append(" FROM ");
        sql.append(defaultTableName);
        alreadyJoinTable.add(defaultTableName);
        int waitForParse;
        do {
            waitForParse = joinRelationshipList.size();
            List<JoinRelationship> delayParseRelationshipList = new ArrayList<>();
            Iterator<JoinRelationship> iterator = joinRelationshipList.iterator();
            while (iterator.hasNext()) {
                JoinRelationship joinRelationship = iterator.next();
                DbField field1;
                DbField field2;
                if (alreadyJoinTable.contains(joinRelationship.getField1().getTable())
                        && !alreadyJoinTable.contains(joinRelationship.getField2().getTable())) {
                    field1 = joinRelationship.getField2();
                    field2 = joinRelationship.getField1();
                } else if (alreadyJoinTable.contains(joinRelationship.getField2().getTable())
                        && !alreadyJoinTable.contains(joinRelationship.getField1().getTable())) {
                    field1 = joinRelationship.getField1();
                    field2 = joinRelationship.getField2();
                } else {
                    if (!alreadyJoinTable.contains(joinRelationship.getField1().getTable())
                            && !alreadyJoinTable.contains(joinRelationship.getField2().getTable())) {
                        delayParseRelationshipList.add(joinRelationship);
                    }
                    iterator.remove();
                    continue;
                }
                sql.append(joinRelationship.getType().getValue());
                sql.append(field1.getTable());
                sql.append(" ON ");
                sql.append(field1.getTable());
                sql.append(".");
                sql.append(field1.getField());
                sql.append(" = ");
                sql.append(field2.getTable());
                sql.append(".");
                sql.append(field2.getField());
                alreadyJoinTable.add(field1.getTable());
                iterator.remove();
            }
            joinRelationshipList.addAll(delayParseRelationshipList);
        } while (waitForParse != joinRelationshipList.size());
        return sql.toString();
    }

    public static String exampleSelectColumns(Class<?> entityClass) {
        StringBuilder sql = new StringBuilder();
        sql.append("<choose>");
        sql.append("<when test=\"@tk.mybatis.mapper.util.OGNL@hasSelectColumns(_parameter)\">");
        sql.append("<foreach collection=\"_parameter.selectColumns\" item=\"selectColumn\" separator=\",\">");
        sql.append("${selectColumn}");
        sql.append("</foreach>");
        sql.append("</when>");
        sql.append("<otherwise>");
        sql.append(getAllColumns(entityClass));
        sql.append("</otherwise>");
        sql.append("</choose>");
        return sql.toString();
    }

    public static String getAllColumns(Class<?> entityClass) {
        Set<EntityColumn> columnSet = EntityHelper.getColumns(entityClass);
        StringBuilder sql = new StringBuilder();
        for (EntityColumn entityColumn : columnSet) {
            sql.append(entityColumn.getColumn())
                    .append(" as ")
                    .append(entityColumn.getColumn().replace(JoinEntityResolve.SPLIT, JoinEntityResolve.COLUMN_SPLIT))
                    .append(", ");
        }
        return sql.substring(0, sql.length() - 2);
    }
}
